package com.qf.osmuser.user.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qf.common.core.constants.AliyunOSSConstants;
import com.qf.common.core.dto.BalanceChangeDTO;
import com.qf.common.core.entity.User;
import com.qf.common.core.entity.UserSign;
import com.qf.common.core.util.JwtUtils;
import com.qf.common.core.util.UserUtils;
import com.qf.common.minio.utils.MinioUtil;
import com.qf.osmuser.user.dto.EditUserDTO;
import com.qf.osmuser.user.mapper.UserMapper;
import com.qf.osmuser.user.mapper.UserSignMapper;
import com.qf.osmuser.user.param.LoginParam;
import com.qf.osmuser.user.service.UserService;
import com.qf.osmuser.user.vo.LoginVO;
import com.qf.osmuser.user.vo.UserInfoVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 天--道--酬--勤
 *
 * @author LiangGaoQiang
 * @ClassName UserServiceImpl
 * @Date: 2025/6/7 21:06
 * @Description: 描述
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private UserSignMapper userSignMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public String login(LoginParam loginParam) {
        // 根据用户名查询用户
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUserName, loginParam.getUsername()));

        // 认证和授权
        if (user == null) {
            throw new RuntimeException("用户名不存在!");
        }
        // 使用Hutool的MD5加密进行密码校验
        String encryptedPassword = DigestUtil.md5Hex(loginParam.getPassword() + user.getSalt());

        if (!user.getUserPassword().equals(encryptedPassword)) {
            throw new RuntimeException("密码错误");
        }

        // 使用JwtToken生成token
        Map<String, Object> map = new HashMap<>();
        map.put("uid", user.getUserId());
        // 生成jwt表示的token
        return JwtUtils.createJwt(map);
    }

    @Override
    public LoginVO getUserInfo(Integer uid) {
        // 根据用户id查询用户信息
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUserId, uid));

        // 将用户信息转换为UserVO对象返回给前端
        LoginVO loginVO = new LoginVO();
        BeanUtils.copyProperties(user, loginVO);

        // 这里需要判断一下用户的头像是否是默认的，如果不是是默认的，则拼接阿里云OSS的URL前缀
        String defaultAvatar = "https://img2.baidu.com/it/u=3846307121,3270602211&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500";
        if (!loginVO.getUserProfilePictureSrc().equals(defaultAvatar)) {
            loginVO.setUserProfilePictureSrc(AliyunOSSConstants.PUBLIC_URL + loginVO.getUserProfilePictureSrc());
        }
        // 返回用户信息
        return loginVO;
    }

    /**
     * 登出
     *
     * @param token 登录token
     */
    @Override
    public void logout(String token) {
        // 删除jwtToken
        JwtUtils.removeJwt(token);
    }

    /**
     * 获取用户信息
     *
     * @return
     */
    @Override
    public UserInfoVO getInfo() {
        // 从ThreadLocal中获取用户uid
        Integer uid = UserUtils.getUid();
        // 根据uid获取用户信息
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUserId, uid));
        return UserInfoVO.builder()
                .id(user.getUserId())
                .username(user.getUserName())
                .phone(user.getUserMobile())
                .realName(user.getUserRealname())
                .gender(user.getUserGender())
                .birth(user.getUserBirthday())
                .avatar(user.getUserProfilePictureSrc())
                .cardNo(user.getCardNo())
                .email(user.getUserEmail())
                .pid(user.getPid())
                .inviteCode(user.getInviteCode())
                .createTime(user.getUserRegisterTime())
                .userMoney(user.getUserMoney())
                .point(user.getPoint())
                .build();
    }

    @Override
    public void update(EditUserDTO editUserDTO) {
        Integer uid = UserUtils.getUid();

        // 查询当前用户对象
        User currentUser = userMapper.selectById(uid);

        // 构建用户对象
        User user = User.builder()
                .userId(uid)
                .userName(editUserDTO.getUsername())
                .userRealname(editUserDTO.getRealName())
                .userMobile(editUserDTO.getPhone())
                .cardNo(editUserDTO.getCardNo())
                .userEmail(editUserDTO.getEmail())
                .userGender(editUserDTO.getGender())
                .userBirthday(editUserDTO.getBirth())
                .build();

        // 校验唯一字段是否被其他用户占用
        checkUniqueFields(currentUser, user);

        // 动态更新：只更新非空字段
        userMapper.update(Wrappers.<User>lambdaUpdate()
                .eq(User::getUserId, uid)
                .set(StringUtils.isNotBlank(user.getUserName()), User::getUserName, user.getUserName())
                .set(StringUtils.isNotBlank(user.getUserRealname()), User::getUserRealname, user.getUserRealname())
                .set(StringUtils.isNotBlank(user.getUserMobile()), User::getUserMobile, user.getUserMobile())
                .set(StringUtils.isNotBlank(user.getCardNo()), User::getCardNo, user.getCardNo())
                .set(StringUtils.isNotBlank(user.getUserEmail()), User::getUserEmail, user.getUserEmail())
                .set(StringUtils.isNotBlank(user.getUserGender()), User::getUserGender, user.getUserGender())
                .set(user.getUserBirthday() != null, User::getUserBirthday, user.getUserBirthday()));
    }

    /**
     * 头像上传
     */
    @Override
    public String uploadAvatar(MultipartFile file) {
        try {
            // 获取原始文件名
            String originalFilename = file.getOriginalFilename();
            // 获取文件输入流
            InputStream inputStream = file.getInputStream();

            // 调用 MinIO 工具类完成上传
            String filePath = minioUtil.upload(originalFilename, inputStream);

            // 将文件路径存入用户表
            userMapper.update(Wrappers.<User>lambdaUpdate()
                    .eq(User::getUserId, UserUtils.getUid())
                    .set(User::getUserProfilePictureSrc, filePath));
            return filePath;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public void sign() {
        // 获取当前用户ID
        Integer uid = UserUtils.getUid();

        // 获取当前日期（转换为只有年月日的java.util.Date）
        Date today = new Date();
        Date todayDateOnly = new java.sql.Date(today.getTime());

        // 判断今日是否已签到
        LambdaQueryWrapper<UserSign> queryWrapper = Wrappers.lambdaQuery(UserSign.class)
                .eq(UserSign::getUserId, uid)
                .eq(UserSign::getSignDate, todayDateOnly);
        UserSign existingSign = userSignMapper.selectOne(queryWrapper);

        if (existingSign != null) {
            throw new RuntimeException("今天已经签到过了");
        }

        // 插入签到记录
        UserSign userSign = UserSign.builder()
                .userId(uid)
                .signDate(today)
                .build();
        userSignMapper.insert(userSign);

        // 增加10积分
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.<User>lambdaUpdate()
                .eq(User::getUserId, uid)
                .setSql("point = point + 10");
        userMapper.update(null, updateWrapper);
    }

    @Override
    public void changeBalance(BalanceChangeDTO dto) {
        String key = "internal_token:" + dto.getInternalToken();
        Boolean exists = redisTemplate.hasKey(key);
        if (exists) {
            redisTemplate.delete(key); // 删除一次性 Token
            User user = userMapper.selectById(dto.getUserId());
            BigDecimal currentMoney = user.getUserMoney();
            BigDecimal newMoney = currentMoney.add(dto.getAmount());

            if (newMoney.compareTo(BigDecimal.ZERO) < 0) {
                throw new RuntimeException("用户余额不足");
            }

            userMapper.update(Wrappers.<User>lambdaUpdate()
                    .set(User::getUserMoney, newMoney)
                    .eq(User::getUserId, dto.getUserId()));
        } else {
            throw new RuntimeException("非法或已过期的内部Token");
        }
    }

    /**
     * 根据用户ID集合获取用户头像集合
     */
    @Override
    public List<String> getAvatarsByUserIds(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }

        // 查询用户头像
        return userMapper.selectList(Wrappers.<User>lambdaQuery()
                        .in(User::getUserId, ids)
                        .select(User::getUserProfilePictureSrc))
                .stream()
                .map(User::getUserProfilePictureSrc)
                .collect(Collectors.toList());
    }


    /**
     * 检查唯一字段是否被其他用户占用
     */
    private void checkUniqueFields(User oldUser, User newUser) {
        LambdaQueryWrapper<User> wrapper;

        if (!StringUtils.equals(oldUser.getUserName(), newUser.getUserName()) && StringUtils.isNotBlank(newUser.getUserName())) {
            wrapper = Wrappers.lambdaQuery(User.class).eq(User::getUserName, newUser.getUserName());
            if (userMapper.exists(wrapper)) {
                throw new RuntimeException("用户名已存在");
            }
        }

        if (!StringUtils.equals(oldUser.getUserMobile(), newUser.getUserMobile()) && StringUtils.isNotBlank(newUser.getUserMobile())) {
            wrapper = Wrappers.lambdaQuery(User.class).eq(User::getUserMobile, newUser.getUserMobile());
            if (userMapper.exists(wrapper)) {
                throw new RuntimeException("手机号已存在");
            }
        }

        if (!StringUtils.equals(oldUser.getCardNo(), newUser.getCardNo()) && StringUtils.isNotBlank(newUser.getCardNo())) {
            wrapper = Wrappers.lambdaQuery(User.class).eq(User::getCardNo, newUser.getCardNo());
            if (userMapper.exists(wrapper)) {
                throw new RuntimeException("身份证号已存在");
            }
        }

        if (!StringUtils.equals(oldUser.getUserEmail(), newUser.getUserEmail()) && StringUtils.isNotBlank(newUser.getUserEmail())) {
            wrapper = Wrappers.lambdaQuery(User.class).eq(User::getUserEmail, newUser.getUserEmail());
            if (userMapper.exists(wrapper)) {
                throw new RuntimeException("邮箱已存在");
            }
        }
    }
}
